package com.baitiaojun.user.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baitiaojun.api.domain.user.UserFollowing;
import com.baitiaojun.api.domain.user.UserInfo;
import com.baitiaojun.api.util.AESUtil;
import com.baitiaojun.api.util.ConstantUtil;
import com.baitiaojun.user.mapper.UserFollowingMapper;
import com.baitiaojun.user.mapper.UserInfoMapper;
import com.baitiaojun.user.service.UserFansService;
import com.baitiaojun.user.service.UserFollowingService;
import com.baitiaojun.user.service.UserInfoService;
import com.baitiaojun.user.support.RedisSupport;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @类名 UserFansServiceImpl
 * @描述 TODO
 * @作者 白条君
 * @创建日期 2023/2/23 20:01
 * @版本 1.0
 */
@Service
public class UserFansServiceImpl implements UserFansService {

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private UserFollowingMapper userFollowingMapper;

    @Resource
    private RedisSupport redisSupport;

    @Resource
    private UserInfoService userInfoService;

    @Autowired
    private UserFollowingService userFollowingService;

    @Override
    public Object getFans(String token, UserFollowing userFollowing) throws Exception {
        //mysql获取所有粉丝的userfollowing关联信息
        Long userid = userFollowing.getUserid();
        Long followingId = userInfoMapper.selectUserInfoByUserId(userid).getId();
        List<UserFollowing> fans = userFollowingMapper.selectFansByUserInfoId(followingId);
        //如果该用户没有粉丝就返回空
        int fansNum = fans.size();
        if (fansNum == 0) {
            Map<String, Object> noFans = new HashMap<>();
            noFans.put("count", fansNum);
            redisSupport.setHash(token, ConstantUtil.Field.FANS.getKey(), noFans);
            return noFans;
        }
        //从redis获取所有粉丝的相关数据
        Object fansFromRedis = redisSupport.getHash(token, ConstantUtil.Field.FANS.getKey());
        List<UserInfo> userInfos = null;
        if (ObjectUtils.isNotEmpty(fansFromRedis)) {
            getJsonFromRedis(fansFromRedis);
        }
        //如果该用户在redis中的数据为空，但是有粉丝就从mysql中查询的fans，并同步redis的数据
        if (ObjectUtils.isEmpty(userInfos)) {
            Map<String, Object> fanMap = getFans(userFollowing);
            redisSupport.setHash(token, ConstantUtil.Field.FANS.getKey(), fanMap);
            return fanMap;
        }
        //如果该用户在redis中的数据不为空，且有粉丝就从mysql中查询的fans，检查是否有粉丝更新，有就重新并同步redis的数据，没有就直接从redis返回
        //从mysql获取所有粉丝的userid
        Set<Long> userids_mysql = userFollowingService.collectUserFollowing(e -> e.getUserid(), fans);
        //从redis获取所有粉丝的userid
        Set<Long> userids_redis = userFollowingService.collectUserFollowing(userInfo -> userInfo.getUserid(), userInfos);
        //将redis中粉丝的userid和mysql中粉丝的userid匹配，只要匹配上就加1，累加个数等于redis中获取的userid的个数就说明mysql中用户粉丝数据没有更新，就直接从redis获取，否则重新从mysql中获取
        AtomicInteger count = new AtomicInteger(0);
        userids_mysql.forEach(userid_redis -> {
            if(userids_mysql.stream().anyMatch(userid_mysql -> userid_mysql.equals(userid_redis))) {
                count.getAndIncrement();
            }
        });
        //如果followed状态不一致也需要也需要重新更新数据
        List<UserFollowing> userFollowings = userFollowingMapper.selectUserFollowingListByUserId(userid);
        Boolean flag = checkFollowedStatus(userInfos, userFollowings);
        //如果和mysql中匹配的数据统计个数和redis中的不一致，就重新更新数据
        if (count.intValue() != userids_redis.size() || flag.equals(true)) {
            //更新数据同步到redis
            Map<String, Object> fanMap = getFans(userFollowing);
            redisSupport.setHash(token, ConstantUtil.Field.FANS.getKey(), fanMap);
            return fanMap;
        }
        return fansFromRedis;
    }

    private List<UserInfo> getJsonFromRedis(Object fansFromRedis) {
        //将fansFromRedis转object，再把object转成string后转成jsonobject
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(fansFromRedis));
        //把jsonobject转string后再转成userinfo
        return JSONArray.parseArray(jsonObject.toJSONString(jsonObject.get("fans")), UserInfo.class);
    }

    private Boolean checkFollowedStatus(List<UserInfo> userInfos, List<UserFollowing> userFollowings) {
        boolean flag = false;
        if (userFollowings.size() > 0) {
            out: for (UserFollowing following : userFollowings) {
                for (UserInfo userInfo : userInfos) {
                    if (following.getFollowingid().equals(userInfo.getUserid())) {
                        if (userInfo.getFollowed() != true) {
                            flag = true;
                            break out;
                        }
                    } else {
                        if (userInfo.getFollowed() != false) {
                            flag = true;
                            break out;
                        }
                    }
                }
            }
        }
        return flag;
    }

    @Override
    public Map<String, Object> getFansList(UserFollowing userFollowing) throws Exception {
        Long userid = userFollowing.getUserid();
        //获取所有粉丝的信息
        Long followingId = userInfoMapper.selectUserInfoByUserId(userid).getId();
        List<UserFollowing> fans = userFollowingMapper.selectFansByUserInfoId(followingId);
        //从mysql获取所有粉丝的userid
        Set<Long> userids = userFollowingService.collectUserFollowing(e -> e.getUserid(), fans);
        //返回的map集合
        Map<String, Object> fansMap = new HashMap<>();
        //如果当前用户没有粉丝，就返回0个粉丝数量的map集合
        if (userids.size() == 0) {
            fansMap.put("count", 0);
            return fansMap;
        }
        //返回的粉丝列表
        List<UserInfo> fansList = new ArrayList<>();
        //获取当前用户的所有粉丝的基本信息
        List<UserInfo> userInfoList = userInfoService.getUserInfoListByUserId(userids, userid);
        //获取当前用户的关注列表
        List<UserFollowing> userFollowings = userFollowingMapper.selectUserFollowingListByUserId(userid);
        AESUtil aesUtil = AESUtil.lazyGetAesUtil();
        for (UserFollowing fan : fans) {
            //给当前粉丝关联用户信息，并把被当前用户关注状态设置为false
            for (UserInfo userInfo : userInfoList) {
                if (userInfo.getUserid().equals(fan.getUserid())) {
                    //当前粉丝的被关注状态初始为false
                    userInfo.setFollowed(false);
                    userInfo.setAvatar(aesUtil.encrypt(userInfo.getAvatar()));
                    //添加当前粉丝的基本信息
                    fan.setUserInfo(userInfo);
                }
            }
            //如果当前用户的关注列表中有关注id和当前粉丝的用户id匹配，就说明当前用户关注了当前粉丝
            userFollowings.forEach(following -> {
                if (following.getFollowingid().equals(userInfoMapper.selectByUserId(fan.getUserid()).getId())) {
                    //当前粉丝的被关注状态改为true，如果这里是true前端就把这个粉丝展现为互粉状态
                    fan.getUserInfo().setFollowed(true);
                }
            });
            //将这个粉丝基本信息添加到粉丝列表
            fansList.add(fan.getUserInfo());
        }
        fansMap.put("fans", fansList);
        return fansMap;
    }

    @Override
    public Map<String, Object> getFans(UserFollowing userFollowing) throws Exception {
        Map<String, Object> fansMap = getFansList(userFollowing);
        List<UserInfo> fansList = (List<UserInfo>) fansMap.get("fans");
        fansList = fansList.stream().peek(userInfo -> {
            userInfo.setUserid(null);
            userInfo.setGender(null);
            userInfo.setFollowing(null);
        }).collect(Collectors.toList());
        //返回粉丝列表和粉丝数量
        fansMap.put("fans", fansList);
        fansMap.put("count", fansList.size());
        return fansMap;
    }

    @Override
    public Integer getFansCount(Long userInfoId) {
        return userFollowingMapper.fansCountByUserInfoId(userInfoId);
    }
}
